#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<errno.h>

#define B_NUM 1024
#define ARGV_NUM 10
#define NONE_REDIR 0
#define INPUT_REDIR 1
#define OUTPUT_REDIR 2
#define APPEND_REDIR 3



char buffer[B_NUM];
char* myargv[ARGV_NUM];
int quitcode=0;
int quitsignal=0;

int redirType=NONE_REDIR;
char* refilename=NULL;


void Commandcheck(char* command)
{
  assert(command);
  //判断是否有重定向，有是哪种
  char* begin=command;
  char* end=command+sizeof command-1;
  
  while(begin<end)
  //while((*begin)!='\0')
  {
    if(*begin=='>')
    {
      *begin='\0';
      begin++;
      if(*begin=='>')
      {
         redirType=APPEND_REDIR;
         begin+=2;
         refilename=begin;
      }
      else{
        redirType=OUTPUT_REDIR;
        refilename=(++begin);
        break;
      }
    }
    if(*begin=='<')
    {
      *begin='\0';
       redirType=INPUT_REDIR;
       begin+=2;
       refilename=begin;
       break;
    }
    begin++;
  }
  return ;
}

int main()
{

  while(1)
  {
    redirType=NONE_REDIR;
    refilename=NULL;
    errno=0;
   
    printf("【用户名@服务器 当前目录】$");
    fflush(stdout);

    char* s=fgets(buffer,sizeof (buffer)-1,stdin);
    assert(s!=NULL);
    buffer[strlen (buffer)-1]=0;
    (void)s;
   
    //和重定向区分开
    Commandcheck(buffer);
    
   // printf("切割成功：命令 %s 文件 %s\n",buffer,refilename);


    //切割字符串
    myargv[0]=strtok(buffer," ");
    int i=0;

    if(myargv[0] != NULL && strcmp(myargv[0], "ls") == 0)
    {
      myargv[++i] = (char*)"--color=auto";
    }

    while(myargv[i]!=NULL)
    {
      myargv[++i]=strtok(NULL," ");
    }

    //实现cd功能
    if(myargv[0] != NULL &&strcmp(myargv[0],"cd")==0)
    {
      if(myargv[1]!=NULL)
      {

        chdir(myargv[1]);
      }
      continue;
    }
    //实现echo $?功能
    if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo")==0)
    {
      if(strcmp(myargv[1],"$?")==0)
      {
        //输出上一个进程的退出码
        printf("退出码为：%d\n",quitcode);

      }
      else
      {
        printf("%s\n",myargv[1]);
      }
      continue;

    }

    pid_t id =fork();
    assert(id!=-1);
    if(id==0)
    {
      //子进程

      //如果有文件打开文件
      switch(redirType)
      {
        case NONE_REDIR:
          break;
        case INPUT_REDIR:
          {
          int fd=open(refilename,O_RDONLY);
            if(fd < 0){           
               perror("open");
               exit(errno);
            }
          dup2(fd,0);
          }
          break;
        case OUTPUT_REDIR:
        case APPEND_REDIR:
          {
            
          int flag=O_WRONLY|O_CREAT;
          if(redirType==OUTPUT_REDIR)
          {
            flag|=O_TRUNC;
          }
          else{
            flag|=O_APPEND;
          }
          umask(0);
          int fd=open(refilename,flag,0666);
            if(fd < 0){            
               perror("open");
               exit(errno);
            }
          dup2(fd,1);
          }
          break;
       default:
          break;

      }


      //程序替换
      execvp(myargv[0],myargv); 
      //如果走到这里表示替换失败
      exit(1);
    }

   //父进程
   int status=0;
   pid_t ret= waitpid(id,&status,0);
   assert(ret > 0);
   (void)ret;
   quitcode=(status>>8)&0XFF;
   quitsignal= (status & 0x7F);

  }
  return 0;
}
